package edu.zju.gis.dldsj.controller;

import edu.zju.gis.dldsj.common.Result;
import edu.zju.gis.dldsj.constant.CodeConstants;
import edu.zju.gis.dldsj.constant.FunctionStatus;
import edu.zju.gis.dldsj.constant.ModelStatus;
import edu.zju.gis.dldsj.entity.Role;
import edu.zju.gis.dldsj.entity.RoleFunction;
import edu.zju.gis.dldsj.entity.RoleModel;
import edu.zju.gis.dldsj.entity.User;
import edu.zju.gis.dldsj.service.RoleFunctionService;
import edu.zju.gis.dldsj.service.RoleModelService;
import edu.zju.gis.dldsj.service.RoleService;
import edu.zju.gis.dldsj.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.sql.Date;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author yanlo yanlong_lee@qq.com
 * @version 1.0 2018/08/10
 */
@Slf4j
@CrossOrigin
@Controller
@RequestMapping(value = "/role")
public class RoleController {
    @Autowired
    private RoleService roleService;
    @Autowired
    private RoleModelService modelService;
    @Autowired
    private RoleFunctionService functionService;
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public String addRole(@SessionAttribute("roleId") String roleId, @RequestBody String requestBody) {
        Result<String> result = new Result<>();
        Role currentRole = roleService.select(roleId);
        if (currentRole == null || !currentRole.getIsAdministrator().equals("true")
                || !currentRole.getStatus().equals(FunctionStatus.NORMAL.name())) {
            result.setCode(CodeConstants.SSO_PERMISSION_ERROR);
            result.setMessage("失败，当前用户无该项权限");
            return result.toString();
        }
        try {
            JSONObject json = new JSONObject(requestBody);
            Role role = new Role();
            role.setName(json.getString("name"));
            role.setDescription(json.optString("description", ""));
            role.setIsAdministrator(String.valueOf(json.getBoolean("isAdministrator")));
            role.setId(UUID.randomUUID().toString());
            role.setRegistrationTime(Date.from(Instant.now()));
            role.setStatus(FunctionStatus.NORMAL.name());
            roleService.insert(role);
            String[] functionIds = json.optString("functionId").split(",");
            List<RoleFunction> functions = new ArrayList<>();
            for (String functionId : functionIds) {
                RoleFunction roleFunction = new RoleFunction();
                roleFunction.setId(UUID.randomUUID().toString());
                roleFunction.setRoleId(role.getId());
                roleFunction.setFunctionId(functionId);
                roleFunction.setRegistrationTime(role.getRegistrationTime());
                roleFunction.setStatus(FunctionStatus.NORMAL.name());
                functions.add(roleFunction);
            }
            functionService.save(functions);
            String[] modelIds = json.optString("modelId").split(",");
            List<RoleModel> models = new ArrayList<>();
            for (String modelId : modelIds) {
                RoleModel roleModel = new RoleModel();
                roleModel.setId(UUID.randomUUID().toString());
                roleModel.setRoleId(role.getId());
                roleModel.setModelId(modelId);
                roleModel.setRegistrationTime(role.getRegistrationTime());
                roleModel.setStatus(ModelStatus.NORMAL.name());
                models.add(roleModel);
            }
            modelService.insert(models);
            result.setCode(CodeConstants.SUCCESS);
            result.setBody("success");
        } catch (JSONException e1) {
            log.error(e1.getMessage());
            result.setCode(CodeConstants.VALIDATE_ERROR);
            result.setMessage(e1.getMessage());
        } catch (RuntimeException e) {
            log.error(e.getMessage());
            result.setCode(CodeConstants.DAO_ERROR);
            result.setMessage(e.getMessage());
        }
        return result.toString();
    }

    @RequestMapping(value = "/update/{roleId}", method = RequestMethod.POST)
    @ResponseBody
    public String update(@PathVariable String roleId, @SessionAttribute("roleId") String currentRoleId, @RequestBody String requestBody) {
        Result<String> result = new Result<>();
        Role currentRole = roleService.select(currentRoleId);
        if (currentRole == null || !currentRole.getIsAdministrator().equals("true")) {
            result.setCode(CodeConstants.SSO_PERMISSION_ERROR);
            result.setMessage("失败，当前用户无该项权限");
            return result.toString();
        }
        try {
            JSONObject json = new JSONObject(requestBody);
            Role role = new Role();
            role.setId(roleId);
            role.setName(json.optString("name", null));
            role.setDescription(json.optString("description", null));
            role.setIsAdministrator(json.has("isAdministrator") ? String.valueOf(json.getBoolean("isAdministrator")) : null);
            role.setRegistrationTime(null);
            roleService.update(role);
            List<String> functionIds = functionService.selectByRoleId(roleId).stream().map(RoleFunction::getId).collect(Collectors.toList());
            List<String> newFunIds = new ArrayList<>();
            Collections.addAll(newFunIds, json.optString("functionId").split(","));
            functionIds.removeAll(newFunIds);
            for (String functionId : functionIds) {
                functionService.delete(roleId, functionId);
            }
            newFunIds.removeAll(functionIds);
            for (String newFunId : newFunIds) {
                RoleFunction roleFunction = new RoleFunction();
                roleFunction.setId(UUID.randomUUID().toString());
                roleFunction.setRoleId(roleId);
                roleFunction.setFunctionId(newFunId);
                roleFunction.setRegistrationTime(Date.from(Instant.now()));
                roleFunction.setStatus(FunctionStatus.NORMAL.name());
                functionService.insert(roleFunction);
            }
            List<String> modelIds = modelService.selectByRoleId(roleId).stream().map(RoleModel::getId).collect(Collectors.toList());
            List<String> newModelIds = new ArrayList<>();
            Collections.addAll(newModelIds, json.optString("modelId").split(","));
            modelIds.removeAll(newModelIds);
            for (String modelId : modelIds) {
                modelService.delete(roleId, modelId);
            }
            newModelIds.removeAll(modelIds);
            for (String newModelId : newModelIds) {
                RoleModel roleModel = new RoleModel();
                roleModel.setId(UUID.randomUUID().toString());
                roleModel.setRoleId(roleId);
                roleModel.setModelId(newModelId);
                roleModel.setRegistrationTime(Date.from(Instant.now()));
                roleModel.setStatus(ModelStatus.NORMAL.name());
                modelService.insert(roleModel);
            }
            result.setCode(CodeConstants.SUCCESS);
            result.setBody("success");
        } catch (RuntimeException e) {
            log.error("角色信息更新失败", e);
            result.setCode(CodeConstants.SERVICE_ERROR).setMessage("角色信息更新失败" + e.getMessage());
        }
        return result.toString();
    }

    @RequestMapping(value = "/delete/{roleId}", method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable String roleId, @SessionAttribute("roleId") String currentRoleId, String option) {
        Role currentRole = roleService.select(currentRoleId);
        if (currentRole == null || !currentRole.getIsAdministrator().equals("true")) {
            return new Result<>(CodeConstants.SSO_PERMISSION_ERROR).setMessage("失败，当前用户无该项权限").toString();
        }
        switch (option) {
            case "getUsers":
                List<User> users = userService.getByRoleId(roleId, 0, Integer.MAX_VALUE);
                return new Result<>(CodeConstants.SUCCESS).setBody(users).toString();
            case "deleteRoleOnly":
                roleService.delete(roleId);
                functionService.deleteByRoleId(roleId);
                modelService.deleteByRoleId(roleId);
                return new Result<>(CodeConstants.SUCCESS).setBody("success").toString();
            case "deleteOnCascade":
                roleService.delete(roleId);
                functionService.deleteByRoleId(roleId);
                modelService.deleteByRoleId(roleId);
                userService.deleteByRoleId(roleId);
                return new Result<>(CodeConstants.SUCCESS).setBody("success").toString();
            default:
                return new Result<>(CodeConstants.VALIDATE_ERROR).setBody("not supported option").toString();
        }
    }
}
